package org.example;

import static java.util.concurrent.ThreadLocalRandom.current;

import cn.hutool.core.util.RandomUtil;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

/**
 * @Title : DeductResp
 * @Description: 划扣执行结果上下问题
 * @author: libo@juzishuke.com
 * @date: 2023/12/21 17:59
 * @Version:1.0
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
@BenchmarkMode(Mode.All)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
public class DeductResp {

    /**
     * 总数量
     */
    private          Long                               total;
    /**
     * 执行完成数量
     */
    private          AtomicLong                         successCnt   = new AtomicLong(0);
    /**
     * 出现异常数量
     */
    private          AtomicLong                         errorCnt     = new AtomicLong(0);
    /**
     * 错误信息
     */
    private volatile ConcurrentHashMap<Integer, String> errorMessage = new ConcurrentHashMap<>();

    public static void main(String[] args) throws RunnerException {
        final Options opts = new OptionsBuilder().include(JMHExample01.class.getSimpleName())
                .forks(1)
                .measurementIterations(10)
                .warmupIterations(10)
                .build();
        new Runner(opts).run();
    }
    @Benchmark
    public void extracted() {
        int total = 1000;
        DeductResp deductResp = DeductResp.builder().total((long) total)
                .successCnt(new AtomicLong(0)).errorCnt(new AtomicLong(0))
                .errorMessage(new ConcurrentHashMap<>()).build();
//        DeductResp deductResp = new DeductResp();
        CountDownLatch countDownLatch = new CountDownLatch(total);
        ExecutorService executorService = new ThreadPoolExecutor(10, 100, 1000L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>());
        for (int i = 0; i < total; i++) {
            int finalI = i;
            executorService.submit(() -> {
                try {
                    TimeUnit.MILLISECONDS.sleep(current().nextInt(20));
                    if (!RandomUtil.randomBoolean()) {
                        throw new Exception(String.valueOf(finalI));
                    }
                    deductResp.getSuccessCnt().getAndIncrement();
                } catch (Exception e) {
                    deductResp.getErrorCnt().getAndIncrement();
                    deductResp.getErrorMessage().put(finalI, e.getMessage());
                } finally {
                    //                    System.out.print(finalI+" ");
                    countDownLatch.countDown();
                }
            });
        }
        System.out.println(deductResp.toString());
        try {
            countDownLatch.await(100, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println();
        System.out.println(deductResp.errorMessage.size());
        System.out.println(deductResp.toString());
    }
}
